/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.meego.common.util;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author TueHM
 */
public class ListUtils {

    public static <T extends Number> List<T> toList(String str, String regex, final Class<T> clazz) {
        return StringUtils.toList(str, regex, clazz);
    }

    public static <T> List<T> subList(List<T> list, int offset, int count) {
        List<T> result = new ArrayList<T>();
        if (list != null) {
            int lsCount = list.size();
            if (offset > lsCount) {
                return result;
            }
            int fromIndex = offset < 0 ? 0 : offset;
            int toIndex = offset + count;
            toIndex = toIndex > lsCount ? lsCount : toIndex;
            result = list.subList(fromIndex, toIndex);
        }
        return result;
    }
    
    public static <T extends Number> List<T> subListWithClone(List<T> list, int offset, int count) {
        List<T> result = new ArrayList<T>();
        if (list != null) {
            int lsCount = list.size();
            if (offset > lsCount) {
                return result;
            }
            int fromIndex = offset < 0 ? 0 : offset;
            int toIndex = offset + count;
            toIndex = toIndex > lsCount ? lsCount : toIndex;
            result.addAll(list.subList(fromIndex, toIndex));
        }
        return result;
    }

    public static List<String> subListStringWithClone(List<String> list, int offset, int count) {
        List<String> result = new ArrayList<String>();
        if (list != null) {
            int lsCount = list.size();
            if (offset > lsCount) {
                return result;
            }
            int fromIndex = offset < 0 ? 0 : offset;
            int toIndex = offset + count;
            toIndex = toIndex > lsCount ? lsCount : toIndex;
            result.addAll(list.subList(fromIndex, toIndex));
        }
        return result;
    }

    public static <T extends Number> List<T> convert(List<String> list, final Class<T> clazz) throws Exception {
        List<T> result = new ArrayList<T>();
        for (String string : list) {
            try {
                if (clazz.equals(Integer.class)) {
                    result.add((T) Integer.valueOf(string));
                } else if (clazz.equals(Long.class)) {
                    result.add((T) Long.valueOf(string));
                } else if (clazz.equals(Float.class)) {
                    result.add((T) Float.valueOf(string));
                } else if (clazz.equals(Double.class)) {
                    result.add((T) Double.valueOf(string));
                } else {
                    throw new Exception(String.format("Type %s is not supported (yet)", clazz.getName()));
                }
            } catch (NumberFormatException e) {
            }
        }
        return result;
    }

    public static <T extends Number> List<String> convert(List<T> list) {
        List<String> result = new ArrayList<String>();
        if (list == null || list.isEmpty()) {
            return result;
        }
        for (T item : list) {
            result.add(String.valueOf(item));
        }
        return result;
    }

    public static <T> void sort(List<T> list, final String compareField, final Class<T> clazz) throws NoSuchFieldException {
        Collections.sort(list, new Comparator<T>() {
            Field fields = clazz.getDeclaredField(compareField);

            @Override
            public int compare(T o1, T o2) {
                try {
                    if (fields.getType().isAssignableFrom(Double.class)) {
                        return Double.valueOf(fields.get(o1).toString()) < Double.valueOf(fields.get(o2).toString()) ? 1 : -1;
                    }
                    if (fields.getType().isAssignableFrom(Long.class)) {
                        return Long.valueOf(fields.get(o1).toString()) < Long.valueOf(fields.get(o2).toString()) ? 1 : -1;
                    }
                    if (fields.getType().isAssignableFrom(Float.class)) {
                        return Float.valueOf(fields.get(o1).toString()) < Float.valueOf(fields.get(o2).toString()) ? 1 : -1;
                    }
                    if (fields.getType().isAssignableFrom(Integer.class)) {
                        return Integer.valueOf(fields.get(o1).toString()) < Integer.valueOf(fields.get(o2).toString()) ? 1 : -1;
                    }
                    if (fields.getType().isAssignableFrom(Short.class)) {
                        return Short.valueOf(fields.get(o1).toString()) < Short.valueOf(fields.get(o2).toString()) ? 1 : -1;
                    }
                    return fields.get(o1).hashCode() <= fields.get(o2).hashCode() ? 1 : -1;
                } catch (Exception ex) {
                    Logger.getLogger(ListUtils.class.getName()).log(Level.SEVERE, null, ex);
                }
                return 0;
            }
        });
    }
}
